﻿# -*- coding: utf-8 -*-

import random
import math
from datetime import date

from core.utils import render_to, birth_date_matcher
from core.models import ProgramModule

from django.core import serializers

from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required, permission_required

from django.db.models import Q
from django.http import Http404, HttpResponse, HttpResponseServerError
from django.shortcuts import get_object_or_404, redirect

from student.models import Student, EnrollmentSheet
from student.forms import EnrollmentSheetEntry, AllSubjectsSelection, ExamGradeForm, ExamGradeCreateExamForm
from exams.models import Professor, Subject, StudentModule, SubjectParticipant, SubjectYear, Exam, ExamApplication

@permission_required('student.can_view_personal')
@render_to("student/student.htm")
def student(request, enrollment_number = None, enrollment_sheet = None):
  """Shows the page for looking at student's personal data.
  """
  if enrollment_number:
    student = get_object_or_404(Student, pk = enrollment_number)

    # Get the enrollment sheet
    if enrollment_sheet is None:
      enrollment_sheet = student.latest_enrollment_sheet
    else:
      enrollment_sheet = get_object_or_404(EnrollmentSheet, pk = enrollment_sheet, student = student)

  else:
    student = None

  # No need to do another searching and stuff
  return {
    'student': student,
    'enrollment_sheet': enrollment_sheet
  }

@login_required
@render_to("student/student_list.htm")

def student_list(request, prof):
  nova_forma = AllSubjectsSelection();
  try:
    if request.user.professor:
      prof = request.user.professor;
      nova_forma.fields['subject'].queryset = Subject.objects.filter(subjectyear__executor__professor = request.user.professor).distinct('pk');
  except:
    nova_forma.fields['subject'].queryset = Subject.objects.filter(subjectyear__executor__professor = prof).distinct('pk');
  if request.method == 'POST':

    forma = AllSubjectsSelection(request.POST)
    if(forma.is_valid()):
      #print 'ALL result count: ' + str(SubjectParticipant.objects.all());
      result = SubjectParticipant.objects.filter(subject__subject = forma.cleaned_data['subject']);
      query_set = SubjectYear.objects.values_list('school_year_start').distinct();
      max_year=0;
      #for i in query_set:
      #  if i[0] > max_year:
      #    max_year = i[0]
      #print 'new year: ' + str(int(forma.cleaned_data['year']));
      max_year = int(forma.cleaned_data['year']);
      #print 'max year: ' + str(max_year);
      #print 'Original result count: ' + str(result.count());
      #dobi samo tiste, ki se nimajo izpita
      if forma.cleaned_data['finished'] == 'True':
        #print 'brez narejenih!'
        for examapp in ExamApplication.objects.filter(exam__subject__subject=forma.cleaned_data['subject']):
          for subpar in result:
            #if subpar.student == examapp.student:
            result = result.exclude(student = examapp.student)


      #spucaj na zadnji letnik
      academic_year = '{0}/{1}'.format(max_year, str(max_year + 1)[2:])
      previous_academic_year = '{0}/{1}'.format(max_year - 1, str(max_year)[2:])
      #print 'result size: ' + str(result.count())
      zblj = []
      result = result.order_by('student__user__last_name', 'student__user__first_name')
      for subpar in result:
        
        if int(forma.cleaned_data['year_combo']) == 1:
          if subpar.subject.school_year_start != max_year:
            result = result.exclude(student = subpar.student)  
        else: 
          if subpar.subject.school_year_start != (max_year-1) and subpar.subject.school_year_start != max_year:
            result = result.exclude(student = subpar.student)
              
      for subpar in result:
        
        if int(forma.cleaned_data['year_combo']) == 1:
          if (subpar.student.enrollment_sheets.filter(academic_year = academic_year).count() > 0):
            zblj.append(subpar.student.enrollment_sheets.get(academic_year = academic_year).enrollment_type)
          else:
            zblj.append('V1')
        else: 
          if subpar.subject.school_year_start == (max_year-1):
            if (subpar.student.enrollment_sheets.filter(academic_year = previous_academic_year).count() > 0):
              zblj.append(subpar.student.enrollment_sheets.get(academic_year = previous_academic_year).enrollment_type)
            else:
              zblj.append('V1')
          elif subpar.subject.school_year_start == max_year:
            if (subpar.student.enrollment_sheets.filter(academic_year = academic_year).count() > 0):
              zblj.append(subpar.student.enrollment_sheets.get(academic_year = academic_year).enrollment_type)
            else:
              zblj.append('V1')
              
      #print 'result count: ' + str(result.count());
      #rang = range(1,len(zblj),1)
      #print zblj;
      #print rang;
      krneki = zip(result, zblj);
      #krneki = krneki.order_by('student__user__last_name', 'student__user__first_name')
      #print krneki
      return{"zippedresult":krneki,"result":result.order_by('student__user__last_name', 'student__user__first_name'),"form_subject":nova_forma, 'professor':prof, 'leto':max_year, "parameters": {
        "subject": forma.cleaned_data["subject"].pk,
        "finished": forma.cleaned_data["finished"],
        "year": forma.cleaned_data["year"],
        "year_combo": forma.cleaned_data["year_combo"]
      }};
    else:
      print 'FAILED TO VALIDATE!';
      return{"form_subject":nova_forma, "form_year":AllSubjectsSelection(), 'professor':prof};
  else:
    return{"form_subject":nova_forma, 'professor':prof};


@login_required
@permission_required('student.can_subjects_selection')
@render_to("student/subjects_selection.htm")
def subjects_selection(request,id=0):
  if id != 0:
    student = Student.objects.get(pk=id)
    available_years = EnrollmentSheet.objects.filter(student=id)
    selected_year = request.GET.get("id")
    en_sheet = student.latest_enrollment_sheet
    if selected_year != None:
      #find correct enrollmentsheet
      selected_year = int(selected_year)
      en_sheet = EnrollmentSheet.objects.get(pk=selected_year)
      
    academic_year_start = en_sheet.academic_year_start()
    academic_year_end = en_sheet.academic_year_end()      
    #izbrani moduli studenta
    modules = StudentModule.objects.filter(student=student, school_year_start=academic_year_start, school_year_end=academic_year_end)
    modules_id = [s.program_module.pk for s in modules]
    spmod = en_sheet.student_program.modules.filter(year = en_sheet.student_year).exclude(pk__in=modules_id).order_by("name")
    
    modules_id_f = list(modules_id)
    if len(modules_id_f) == 0:
      modules_id_f = [-11]    
    
    #predmeti studenta
    subjects = SubjectParticipant.objects.filter(
      Q(
        Q(student=student,
        subject__school_year_start=academic_year_start,
        subject__school_year_end=academic_year_end),
        Q(subject__subject__subjectprogram__year__exact=en_sheet.student_year) | Q(subject__subject__subjectprogram__year__isnull=True)
      ),
      Q(subject__subject__subjectprogram__obligatory=False) | Q(subject__subject__subjectprogram__obligatory=True, subject__subject__program_module__isnull=False)
    ).exclude(Q(subject__subject__program_module__id__in=modules_id_f),~Q(subject__subject__program_module__isnull=True)).order_by("subject__subject__name")
    
    subjects_id = [x.subject.subject.code for x in subjects]
    ssubjects = en_sheet.student_program.subjects.exclude(code__in=subjects_id).filter(
      Q(subjectprogram__obligatory=False) | 
      Q(program_module__isnull=False),
      Q(subjectprogram__year__exact=en_sheet.student_year) | Q(subjectprogram__year__isnull=True)
    ).order_by("name")
    
    print "Izbrani",len(subjects)
    

    error_to_many_modules  = False

    if request.method == 'POST':
      #save modified modules
      selected_modules = [ int(x) for x in request.POST.getlist('selected_module')]

      print "izbrani moduli: ",selected_modules
      print "moduli: ",modules_id
      need_to_delete = list(set(modules_id)-set(selected_modules))
      need_to_save = list(set(selected_modules)-set(modules_id))

      count_modules = len(modules)+len(need_to_save) - len(need_to_delete)
      if count_modules <= 2:
        for module_id in need_to_save:
          module = ProgramModule.objects.get(pk=module_id)
          st_module = StudentModule(student=student,program_module=module,school_year_start=academic_year_start,school_year_end=academic_year_end)
          st_module.save()
          subjects_to_add = SubjectYear.objects.filter(subject__program_module=module, school_year_start=academic_year_start,school_year_end=academic_year_end)
          for s in subjects_to_add:
            st_subject = SubjectParticipant(subject=s,student=student)
            st_subject.save()

        print need_to_delete
        for module_id in need_to_delete:
          st_module = StudentModule.objects.get(student=student,program_module__id=module_id,school_year_start=academic_year_start,school_year_end=academic_year_end)
          if st_module:
            st_module.delete()
          subjects_to_remove =  SubjectYear.objects.filter(subject__program_module=module_id, school_year_start=academic_year_start,school_year_end=academic_year_end)
          for s in subjects_to_remove:
            st_subject = SubjectParticipant.objects.get(subject=s,student=student)
            if st_subject:
              st_subject.delete()

        #save modified subjects
        selected_subjects = request.POST.getlist('selected_subject')

        need_to_delete = list(set(subjects_id)-set(selected_subjects))
        need_to_save = list(set(selected_subjects)-set(subjects_id))

        for subject_id in need_to_delete:
          subject = SubjectParticipant.objects.get(student=student,subject__subject__code=subject_id, subject__school_year_start=academic_year_start,subject__school_year_end=academic_year_end)
          subject.delete()

        for subject_id in need_to_save:
          subject = SubjectYear.objects.get(subject__code=subject_id,school_year_start=academic_year_start,school_year_end=academic_year_end)
          st_subject = SubjectParticipant(subject=subject,student=student)
          st_subject.save()

        if (selected_year):
          return redirect('/student/subjects_selection/'+id+'/?id='+str(selected_year))
        else:
          return redirect('/student/subjects_selection/'+id+'/')
      else:
        error_to_many_modules = True   
    
    return {"enrollment_sheet":en_sheet,
            "selected_year":selected_year,
            "available_years":available_years,
            "student":student,
            "spmod":spmod,
            "smod":modules,
            "ssubjects":ssubjects,
            "selsub":subjects,
            "error_to_many_modules":error_to_many_modules
           }
  else:
    return {"only_search":True}

@permission_required('student.add_enrollmentsheet')
@render_to("student/enrollment_sheet_entry.htm")
def enrollment_sheet_entry(request):
  # Make the current academic year
  if date.today().month < 7:
    this_year = date.today().year - 1
  else:
    this_year = date.today().year
  next_year = str(this_year + 1)
  academic_year = '%d/%s' % (this_year, next_year[2:])

  added = False
  # Get student if the user is student
  try:
    student = request.user.student
  except:
    student = None

  if request.method == 'POST':
    form = EnrollmentSheetEntry(request.POST, request.FILES)

    if form.is_valid():
      form.save()

      # Redirect if student
      if student is not None:
        return redirect('index')

      # Add new if clerk
      form = EnrollmentSheetEntry(initial = {'academic_year': academic_year})
      added = True
  elif student is None:
    form = EnrollmentSheetEntry(initial = {'academic_year': academic_year})
  elif student.latest_enrollment_sheet.academic_year == academic_year:
    # There is nothing to add
    form = None
  else:
    form = EnrollmentSheetEntry(initial = {'academic_year': academic_year}, instance = student.latest_enrollment_sheet)

    # Make some protection, so student wouldn't add another student
    form.fields['emso'].widget.attrs['readonly'] = True
    form.fields['vat_number'].widget.attrs['readonly'] = True
    form.fields['academic_year'].widget.attrs['readonly'] = True

  return {
    'enrollment_entry': form,
    'added': added
  }

@login_required
@permission_required('student.can_exam_result_paper')
@render_to("student/exam_result_paper.htm")
def exam_result_paper(request, id=0):
  if id == 0:
    return {"only_search":True}
  else:
    application = None
    subject = None
    if request.GET.get("application"):
      application = int(request.GET.get("application"))
    if request.GET.get("subject"):
      subject = int(request.GET.get("subject"))
    student = Student.objects.get(pk = id)
    exams = ExamApplication.objects.filter(student=student,grade_date__isnull=True)
    spart = [s.subject.pk for s in SubjectParticipant.objects.filter(student = student)]
    subjects = SubjectYear.objects.filter(pk__in=spart)
    
    professor = None
    try:
      if (request.user.professor):
       professor = request.user.professor
       subjects = subjects.filter(professors=request.user.professor).distinct()
       exams = exams.filter(exam__subject__professors=request.user.professor).distinct()
    except Exception,e:
      pass

    if application:
      app_obj = ExamApplication.objects.get(pk = application)

      if request.method == 'POST':
        form = ExamGradeForm(request.POST,instance = app_obj)
        if form.is_valid():
          form.save()
          return redirect('student_exam_result_paper_sel', student.enrollment_number)
      else:
        app_obj.grade_date = app_obj.exam.date
        form = ExamGradeForm(instance = app_obj)
      if app_obj.exam.rating_type == "OC1":
        #ocena vaj in ocena izpita
        pass
      elif app_obj.exam.rating_type == "OC2":
        #ocena vaj
        form.fields['exam_grade'].widget.attrs['disabled'] = 'disabled'
        pass
      elif app_obj.exam.rating_type == "OC3":
        #ocena izpita
        form.fields['practice_grade'].widget.attrs['disabled'] = 'disabled'
      return {"only_search":False,"student":student,"exams":exams,"subjects":subjects,"application":application,"app_obj":app_obj,"form":form }
    elif subject:
      default = {"subject":str(subject)}
      data = dict(request.POST.items() + default.items())
      form = ExamGradeCreateExamForm(data,subject=SubjectYear.objects.get(pk=subject),professor=professor)
      form.fields["subject"].initial = subject
      form.fields['subject'].widget.attrs['readonly'] = True
      
      tries = SubjectYear.objects.get(pk=subject).subject.number_applies_str(student)
      
      
      if request.method == 'POST':
        if form.is_valid():
          exam = form.save()
          exam.special = True
          exam.save()
          exam_application = ExamApplication(exam = exam, student = student, application_date = date.today())
          try:
            exam_application.clean()
            exam_application.save()
            return redirect('/student/exam_result_paper/'+student.enrollment_number+'/?application='+str(exam_application.pk))   
          except Exception,e:
            elist = []
            for k in e.messages:
              elist.append(k)
            form._errors["subject"] = form.error_class(elist)
                 
      return {"tries":tries,"only_search":False,"student":student,"exams":exams,"subjects":subjects,"subject":subject,"form":form}
    else:
      return {"only_search":False,"student":student,"exams":exams,"subjects":subjects}
